﻿using DefaultDspPluginsLib;
using SoundEngine3.AudioProcessing;
using SoundEngine3.DspPlugins;
using SoundEngine3.DspPlugins.Meta;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using ZquenceStudio3.Core;
using ZquenceStudio3.Core.DspPlugins;
using ZquenceStudio3.DspPlugins;

namespace ZquenceStudio.DefaultDspPlugins.Effects
{
    public class DistortionDescription : IDspPlugin
    {
        public DspPluginInfo GetDspPluginInfo()
        {
            return new DspPluginInfo("Distortion", DspType.Effect);
        }

        public BaseDspPluginInstance CreateDsp(ZquenceStudio3Context context, DspPluginInfo info)
        {
            return new Distortion(context, info);
        }
    }

    public class Distortion : CoreDspEffectPlugin
    {
        public struct DistortionData
        {
            public int Channels;
            public int Length;
            public double Output;
            public double Dist;
        }

#if !Portable
        [DllImport(NativeSoundEngineDllImport.Dll)]
        public static extern void Effect_Distortion_Process(ref DistortionData data,
            ref double wav_in_left, ref double wav_in_right, ref double wav_out_left, ref double wav_out_right);
#endif

        private const double heigh = short.MaxValue;
        private const double peak = 1d / heigh;
        
        public double Dist { get; set; }
        public double Output { get; set; }

        public Distortion(ZquenceStudio3Context application, DspPluginInfo info)
            : base(application, info)
        {
            Dist = 0.5;
            Output = 0.6;

            CreateParameters();

            SupportAudioProcessing = true;
        }

        private void CreateParameters()
        {
            // Dist.
            ParameterPropertiesDirect dist = new ParameterPropertiesDirect(this);
            dist.Label = "Dist";
            dist.DirectGet += delegate() { return Dist; };
            dist.DirectSet += delegate(double value) { Dist = value; };
            dist.MinValue = 0;
            dist.MaxValue = 1;
            AddParameter(dist);

            // Output.
            ParameterPropertiesDirect output = new ParameterPropertiesDirect(this);
            output.Label = "Output";
            output.DirectGet += delegate() { return Output; };
            output.DirectSet += delegate(double value) { Output = value; };
            output.MinValue = 0;
            output.MaxValue = 1;
            AddParameter(output);
        }

        public override Version Version
        {
            get { return DspPluginInfo.DefaultVersion; }
        }

        public override string PluginInfo
        {
            get { return DspPluginInfo.DefaultPluginInfo; }
        }
        
        public override void Process(BaseAudioBuffer input, BaseAudioBuffer output)
        {
            DistortionData data;
            data.Length = input.Channels[0].Samples.Length;
            data.Output = Output;
            data.Dist = Dist;
            data.Channels = input.Channels.Length;

            if (NativeSoundEngineDllImport.UseBenchmarking)
            {
                ZquenceStudio3.Core.Utils.ProfilerMeter.Start1("Distortion");
#if !Portable
                Effect_Distortion_Process(ref data, ref input.Channels[0].Samples[0], ref input.Channels[1].Samples[0], ref output.Channels[0].Samples[0], ref output.Channels[1].Samples[0]);
#endif
                ZquenceStudio3.Core.Utils.ProfilerMeter.Stop1("Distortion");
                ZquenceStudio3.Core.Utils.ProfilerMeter.Start2("Distortion");
                DefaultDspPluginsLib.Depricated.Effect_Distortion.Process(ref data, input.Channels[0].Samples, input.Channels[1].Samples, output.Channels[0].Samples, output.Channels[1].Samples);
                ZquenceStudio3.Core.Utils.ProfilerMeter.Stop2("Distortion");
            }
            else
            {
                if (NativeSoundEngineDllImport.UseNativeProcessing)
                {
#if !Portable
                    Effect_Distortion_Process(ref data, ref input.Channels[0].Samples[0], ref input.Channels[1].Samples[0], ref output.Channels[0].Samples[0], ref output.Channels[1].Samples[0]);
#endif
                }
                else
                {
                    DefaultDspPluginsLib.Depricated.Effect_Distortion.Process(ref data, input.Channels[0].Samples, input.Channels[1].Samples, output.Channels[0].Samples, output.Channels[1].Samples);
                }
            }
        }
        
        protected override void OnProcessEvents(List<SoundEngine3.MIDI.Meta.MidiMessage> midiMessages)
        {

        }
    }
}
